﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;

namespace GestionCegep.Objects
{
    public class Etudiant : PersistentObject
    {
        private static Etudiant oldEtudiant = new Etudiant("");

        // Différentes requetes a la base de donnees pour la gestion des enseignants
        private const string selectQuery = "SELECT MATRICULE, CODE_PERMANENT_GOUV, NOM, PRENOM, TELEPHONE FROM ETUDIANT";
        private const string lockQuery = "LOCK TABLE ETUDIANT IN EXCLUSIVE MODE";
        private const string insertQuery = "INSERT INTO ETUDIANT(MATRICULE) VALUES('{0}')";
        private const string updateQuery = "UPDATE ETUDIANT SET CODE_PERMANENT_GOUV = '{1}', NOM = '{2}', PRENOM = '{3}', TELEPHONE = '{4}' WHERE MATRICULE = '{0}'";
        private const string deleteQuery = "DELETE FROM ETUDIANT WHERE MATRICULE = '{0}'";

        private string matricule;           // Matricule de l'etudiant
        private string codePermanantGouv;   // Code permanent de l'etudiant
        private string nom;                 // Nom de l'etudiant
        private string prenom;              // Prenom de l'etudiant
        private string telephone;           // Numero de telephone de l'etudiant

        // Constructeur
        private Etudiant(string matricule, string codePermanantGouv, string nom, string prenom, string telephone, bool isNew = false)
        {
            this.matricule = matricule;
            this.codePermanantGouv = codePermanantGouv;
            this.nom = nom;
            this.prenom = prenom;
            this.telephone = telephone;
            this.isNew = isNew;
        }
        public Etudiant(string matricule)
        {
            this.matricule = matricule;
            isNew = true;
        }
        public Etudiant(string matricule, string codePermanantGouv, string nom, string prenom, string telephone)
        {
            this.matricule = matricule;
            this.codePermanantGouv = codePermanantGouv;
            this.nom = nom;
            this.prenom = prenom;
            this.telephone = telephone;
            this.isNew = true;
        }

        public string Matricule { get { return matricule; } set { matricule = value; isModified = true; } }
        public string CodePermanentGouv { get { return codePermanantGouv; } set { codePermanantGouv = value; } }
        public string Nom { get { return nom; } set { nom = value; } }
        public string Prenom { get { return prenom; } set { prenom = value; } }
        public string Telephone { get { return telephone; } set { telephone = value; } }
        public string NomComplet { get { return nom + ", " + prenom; } }


        // Insertion de l'etudiant dans la base de données
        public override void InsertIntoDataBase(OracleConnection OracleConnection, DataStore dataStore)
        {
            OracleCommand command;
            try
            {
                command = OracleConnection.CreateCommand(); // Creation de la commande Oracle
                command.CommandText = lockQuery; // Verouillage de la table Etudiant
                command.ExecuteNonQuery();

                command.CommandText = String.Format(insertQuery, matricule); // Insertion dans la base de données
                command.ExecuteNonQuery();

                // Journalisation des modifications
                dataStore.CurrentTransaction.PushLogToBD(LogActions.Defaire, String.Format(deleteQuery, matricule));
                dataStore.CurrentTransaction.PushLogToBD(LogActions.Refaire, String.Format(insertQuery, matricule));

                dataStore.CurrentTransaction.Commit(); // Confirmation de la transaction
                dataStore.Etudiants.Add(this); // Ajout de l'etudiant a la liste des etudiants
            }
            catch (OracleException exception)
            {
                throw exception;
            }
        }

        // Vérouillage pour la mise a jour
        public override void LockForUpdate(OracleConnection OracleConnection)
        {
            try
            {
                OracleCommand command = OracleConnection.CreateCommand(); // Creation de la commande
                command.CommandText = selectQuery + " WHERE MATRICULE = '" + matricule + "' FOR UPDATE"; // Verouillage pour la mise a jour
                command.ExecuteScalar();

                oldEtudiant.matricule = matricule;
                oldEtudiant.codePermanantGouv = codePermanantGouv;
                oldEtudiant.nom = nom;
                oldEtudiant.prenom = prenom;
                oldEtudiant.telephone = telephone;
            }
            catch (OracleException exception)
            {
                throw exception;
            }
        }

        // Mise a jour dans la base de données
        public override void UpdateIntoDataBase(MyOracleTransaction currentTransaction)
        {
            try
            {
                OracleCommand command = currentTransaction.Connection.CreateCommand(); // Creation d'une nouvelle commande Oracle
                command.CommandText = String.Format(updateQuery, matricule, CodePermanentGouv, nom, prenom, telephone); // Mise a jour dans la base de données
                command.ExecuteNonQuery();

                // Journalisation des modifications
                currentTransaction.PushLogToBD(LogActions.Defaire, String.Format(updateQuery, oldEtudiant.matricule, oldEtudiant.codePermanantGouv, oldEtudiant.nom, oldEtudiant.prenom, oldEtudiant.telephone));
                currentTransaction.PushLogToBD(LogActions.Refaire, command.CommandText);

                currentTransaction.Commit(); // Confirmation de la transaction
            }
            catch (OracleException exception)
            {
                codePermanantGouv = oldEtudiant.codePermanantGouv;
                nom = oldEtudiant.nom;
                prenom = oldEtudiant.prenom;
                telephone = oldEtudiant.telephone;
                throw exception;
            }
        }

        // Suppression dans la base de données
        public override void DeleteFromDataBase(OracleConnection OracleConnection, DataStore dataStore)
        {
            OracleCommand command;
            try
            {
                command = OracleConnection.CreateCommand(); // Creation de la commande Oracle
                command.CommandText = lockQuery; // Vérouillage de la table
                command.ExecuteNonQuery();

                command.CommandText = String.Format(deleteQuery, matricule); // Suppression de l'etudiant de la base de donnees
                command.ExecuteNonQuery();

                // Journalisation des modifications
                string insertQuery = "INSERT INTO ETUDIANT VALUES('{0}','{1}',{2},{3},{4})";
                dataStore.CurrentTransaction.PushLogToBD(LogActions.Defaire, String.Format(insertQuery, matricule, codePermanantGouv, nom, prenom, telephone));
                dataStore.CurrentTransaction.PushLogToBD(LogActions.Refaire, command.CommandText);

                dataStore.CurrentTransaction.Commit(); // Confirmation de la transaction
                dataStore.Etudiants.Remove(this); // On retire l'etudiant de la liste des etudiants
            }
            catch (OracleException exception)
            {
                throw exception;
            }
        }

        // Balayage de la table etudiants pour obtenir toutes les informations
        public static List<Etudiant> GetEtudiantsFromDataBase(OracleConnection OracleConnection)
        {
            List<Etudiant> etudiants = new List<Etudiant>(); // Liste des etudiants

            try
            {
                OracleCommand command = OracleConnection.CreateCommand(); // Creation de la commande Oracle
                command.CommandText = "SELECT MATRICULE, CODE_PERMANENT_GOUV, NOM, PRENOM, TELEPHONE FROM ETUDIANT";
                OracleConnection.Open(); // Ouverture de la connexion
                OracleDataReader reader = command.ExecuteReader(); // Execution de la requete select

                // Tant qu'il y a des donnees dans la table Etudiant
                while (reader.Read())
                {
                    Etudiant etudiant = new Etudiant(reader["MATRICULE"].ToString(),
                                                    reader["CODE_PERMANENT_GOUV"].ToString(),
                                                    reader["NOM"].ToString(),
                                                    reader["PRENOM"].ToString(),
                                                    reader["TELEPHONE"].ToString(),
                                                    false);
                    etudiants.Add(etudiant); // Ajout de tout les etudiants a la liste des etudiants
                }
                OracleConnection.Close(); // Fermeture de la connexion
            }
            catch (OracleException exception)
            {
                throw exception;
            }

            return etudiants; // On retourne les etudiants pour le remplissable du DataGridView
        }
    }
}
